
#include <stdio.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "driver/gpio.h"
#include "freertos/queue.h"
#include "freertos/event_groups.h"
#include "esp_task_wdt.h"
#include <esp_log.h>

uint32_t time=0,time1=0,time2=0;
bool syn_flag=false;

const static char *TAG = "ESP32_SYN";

#define SENDER_BIT BIT0

#define PIN_INTR  0
#define GPIO_INTR_PIN  (1ULL<<PIN_INTR) 
#define ESP_INTR_FLAG_DEFAULT 0

static xQueueHandle gpio_evt_queue = NULL;
EventGroupHandle_t g_event_group;

#define TWDT_TIMEOUT_S          5
#define TASK_RESET_PERIOD_S     2
static TaskHandle_t task_handles[portNUM_PROCESSORS];

#define CHECK_ERROR_CODE(returned, expected) ({                        \
            if(returned != expected){                                  \
                printf("TWDT ERROR\n");                                \
                abort();                                               \
            }                                                          \
})


void Sync_Task();
//GPIO中断服务函数
static void IRAM_ATTR gpio_isr_handler(void* arg)
{    
	
    if(syn_flag==false)
    {
        time1=esp_timer_get_time(); 
        syn_flag=true;
		// Sync_Task();

        // xEventGroupSetBits(g_event_group, SENDER_BIT);
		
		// uint32_t gpio_num = (uint32_t) arg; 
        // xQueueSendFromISR(gpio_evt_queue, &gpio_num, NULL); 
    }    
}

void gpio_init()
{
    gpio_config_t io_conf = {};

    //interrupt of rising edge
    io_conf.intr_type = GPIO_INTR_POSEDGE;
    //bit mask of the pins, use GPIO2 here
    io_conf.pin_bit_mask = GPIO_INTR_PIN;
    //disable pull-down mode
    io_conf.pull_down_en = 0;
    //enable pull-up mode
    io_conf.pull_up_en = 1;
    //set as input mode
    io_conf.mode = GPIO_MODE_INPUT;

    gpio_config(&io_conf);

    //change gpio intrrupt type for one pin
    gpio_set_intr_type(PIN_INTR, GPIO_INTR_ANYEDGE);

	//创建队列
    gpio_evt_queue = xQueueCreate(10, sizeof(uint32_t));
    //install gpio isr service
    gpio_install_isr_service(ESP_INTR_FLAG_DEFAULT);
    //hook isr handler for specific gpio pin
    gpio_isr_handler_add(PIN_INTR, gpio_isr_handler, (void*) PIN_INTR);

    ESP_LOGI(TAG,"%s","开启IO中断");
}

//同步信号执行任务
void Sync_Task()
{
	ESP_LOGI(TAG, "%s","信号同步任务执行");
}

//Callback for user tasks created in app_main()
void reset_task(void *arg)
{
    //Subscribe this task to TWDT, then check if it is subscribed
    CHECK_ERROR_CODE(esp_task_wdt_add(NULL), ESP_OK);
    CHECK_ERROR_CODE(esp_task_wdt_status(NULL), ESP_OK);

    while(1){
        //reset the watchdog every 2 seconds
        CHECK_ERROR_CODE(esp_task_wdt_reset(), ESP_OK);//喂狗  //Comment this line to trigger a TWDT timeout
        vTaskDelay(pdMS_TO_TICKS(TASK_RESET_PERIOD_S * 1000));
    }
}


void app_main()
{

	ESP_LOGI(TAG, "ESP32 Start!");

	gpio_init();

	while(1)
	{	
		//等待标志位---精度<=10ms
		// while(!syn_flag){
		// 	vTaskDelay(10 / portTICK_PERIOD_MS);
		// 	ESP_LOGI(TAG, "%s","等待同步信号....");
		// }
		// time2=esp_timer_get_time(); 
		// if(syn_flag)
		// {
		// 	Sync_Task();
		// }
		// time=time2-time1;
		// ESP_LOGI(TAG, "同步精度:%dus",time);

		//队列---精度<=10ms
		// uint32_t io_num;
		// if(xQueueReceive(gpio_evt_queue,&io_num, portMAX_DELAY))
		// {
		// 	time2=esp_timer_get_time(); 
		// 	Sync_Task();	
		// 	time=time2-time1;
		// 	ESP_LOGI(TAG, "同步精度:%dus",time);
		// 	ESP_LOGI(TAG, "IO口:%d中断",io_num);
		// }

		//事件组---精度<=10ms
        // g_event_group = xEventGroupCreate();
        // EventBits_t bits = xEventGroupWaitBits(g_event_group, SENDER_BIT, pdTRUE, pdFALSE, portMAX_DELAY);
        // if (bits & SENDER_BIT) 
        // {
        //     time2=esp_timer_get_time(); 
		// 	Sync_Task();
        //     time=time2-time1;
		// 	ESP_LOGI(TAG, "同步精度:%dus",time);
        // }

		CHECK_ERROR_CODE(esp_task_wdt_init(TWDT_TIMEOUT_S, false), ESP_OK);
    #ifndef CONFIG_ESP_TASK_WDT_CHECK_IDLE_TASK_CPU0
        esp_task_wdt_add(xTaskGetIdleTaskHandleForCPU(0));
    #endif
    #if CONFIG_ESP_TASK_WDT_CHECK_IDLE_TASK_CPU1 && !CONFIG_FREERTOS_UNICORE
        esp_task_wdt_add(xTaskGetIdleTaskHandleForCPU(1));
    #endif


    	//Create user tasks and add them to watchdog
		for(int i = 0; i < portNUM_PROCESSORS; i++)
		{
			xTaskCreatePinnedToCore(reset_task, "reset task", 1024, NULL, 10, &task_handles[i], i);
		}

		for(int i = 0; i < portNUM_PROCESSORS; i++)
		{
			vTaskDelete(task_handles[i]);   //Delete user task first (prevents the resetting of an unsubscribed task)
			CHECK_ERROR_CODE(esp_task_wdt_delete(task_handles[i]), ESP_OK);     //Unsubscribe task from TWDT
			CHECK_ERROR_CODE(esp_task_wdt_status(task_handles[i]), ESP_ERR_NOT_FOUND);  //Confirm task is unsubscribed

			//unsubscribe idle task
			CHECK_ERROR_CODE(esp_task_wdt_delete(xTaskGetIdleTaskHandleForCPU(i)), ESP_OK);     //Unsubscribe Idle Task from TWDT
			CHECK_ERROR_CODE(esp_task_wdt_status(xTaskGetIdleTaskHandleForCPU(i)), ESP_ERR_NOT_FOUND);      //Confirm Idle task has unsubscribed
		}


		//Deinit TWDT after all tasks have unsubscribed
		CHECK_ERROR_CODE(esp_task_wdt_deinit(), ESP_OK);
		CHECK_ERROR_CODE(esp_task_wdt_status(NULL), ESP_ERR_INVALID_STATE);     //Confirm TWDT has been deinitialized

		while(!syn_flag){
			//救狗----喂狗 ---精度<10us
		}
		time2=esp_timer_get_time(); 
		if(syn_flag)
		{
			Sync_Task();
		}
		time=time2-time1;
		ESP_LOGI(TAG, "同步精度:%dus",time);

	
		while(1)
		{
			vTaskDelay(1000 / portTICK_PERIOD_MS);
		}
	}

}
